suite("path-walker", function () {
    "use strict";

    var PathWalker = require("./path-walker");
    var assert = require("assert");

    test("parse empty", function () {
        assert(PathWalker.splitFirst("") === null);
    });

    test("parse single name", function () {
        assert(PathWalker.splitFirst("some") === null);
    });

    test("parse single dot", function () {
        var parsed = PathWalker.splitFirst(".");
        assert(parsed.first === "");
        assert(parsed.rest === "");
    });

    test("parse two parts", function () {
        var parsed = PathWalker.splitFirst("a.b");
        assert(parsed.first === "a");
        assert(parsed.rest === "b");
    });

    test("parse three parts", function () {
        var parsed = PathWalker.splitFirst("a.b.c");
        assert(parsed.first === "a");
        assert(parsed.rest === "b.c");
    });

    test("parse escaped", function () {
        assert(PathWalker.splitFirst("\\.\\.") === null);
        assert(PathWalker.splitFirst("\\\\\\.\\\\\\.") === null);
    });

    test("parse escaped escape", function () {
        var parsed = PathWalker.splitFirst("\\\\.");
        assert(parsed.first === "\\");
        assert(parsed.rest === "");
    });

    test("parse escaped dot", function () {
        var parsed = PathWalker.splitFirst("\\..");
        assert(parsed.first === ".");
        assert(parsed.rest === "");
    });

    test("parse escaped rest", function () {
        var parsed = PathWalker.splitFirst("a.\\.");
        assert(parsed.first === "a");
        assert(parsed.rest === "\\.");
    });

    test("parse single path", function () {
        assert(PathWalker.get({a: 1}, "a") === 1);
    });

    test("get no rest", function () {
        assert(PathWalker.get({a: 1}, "a.b") === undefined);
    });

    test("get rest", function () {
        assert(PathWalker.get({a: {b: 1}}, "a.b") === 1);
    });

    test("set single path", function () {
        var instance = {};
        PathWalker.set(instance, "a", 1);
        assert(instance.a === 1);
    });

    test("set no rest", function () {
        var instance = {};
        try {
            PathWalker.set(instance, "a.b", 1);
            assert(false);
        } catch (error) {
            assert(error.message.indexOf("undefined") >= 0);
        }
    });

    test("set rest", function () {
        var instance = {a: {}};
        PathWalker.set(instance, "a.b", 1);
        assert(instance.a.b === 1);
    });

    test("escape dots", function () {
        assert(PathWalker.escapeName("..") === "\\.\\.");
    });

    test("escape escapes", function () {
        assert(PathWalker.escapeName("\\\\") === "\\\\\\\\");
    });

    test("find arrays", function () {
        var array = [1, 2, 3];
        var object = {array: array};
        assert(PathWalker.get(object, "array.1") === 2);
    });

    test("join returns undefined when no args", function () {
        var path = PathWalker.join();
        assert(path === undefined);
    });

    test("join returns escaped name when single args", function () {
        var name = ".a";
        var path = PathWalker.join(name);
        assert(path === PathWalker.escapeName(name));
    });

    test("join returns joined names when multiple args", function () {
        var name0 = ".a";
        var name1 = "b";
        var name2 = "c";
        var path = PathWalker.join(name0, name1, name2);
        assert(path === PathWalker.escapeName(name0) + "." +
            PathWalker.escapeName(name1) + "." +
            PathWalker.escapeName(name2));
    });

    test("join ignores empty names", function () {
        var name0 = "";
        var name1 = "b";
        var path = PathWalker.join(name0, name1);
        assert(path === name1);
    });

    test("join handles indexes", function () {
        var name0 = "a";
        var name1 = 42;
        var name2 = "c";
        var path = PathWalker.join(name0, name1, name2);
        assert(path === PathWalker.escapeName(name0) + "." +
            PathWalker.escapeName(name1) + "." +
            PathWalker.escapeName(name2));
    });
});
